JAVA创建代理时的lang.ClassCastException
我的目标是从class
创建一个实例,它实现了一个interface
并扩展了另一个class
。。。实体注释:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface Entity {
String visibileName();
}
。。。实现IEventDesignDialog
public class EventDesignDialog implements IEventDesignDialog{
private String show;
private String dateAndTimeDisplayFormat;
private String eventType;
@Entity(visibileName = "Show")
public String getShow() {
return this.show;
}
@Entity(visibileName = "Date And Time display format")
public String getDateAndTimeDisplayFormat() {
return this.dateAndTimeDisplayFormat;
}
@Entity(visibileName = "Event Type")
public String getEventType() {
System.out.println("get event type method invokde successfully");
return this.eventType;
}
}
IEventDesignDialog
接口:
public interface IEventDesignDialog extends IPage{
public String getShow();
public String getDateAndTimeDisplayFormat();
public String getEventType();
}
IPage
接口:
public interface IPage {
}
动态代理实现:
public class IPageProxy implements InvocationHandler {
private List<Method> entityMethods;
private Class <? extends IPage> screenClazz;
public IPageProxy(final Class <? extends IPage> screenClazz) {
entityMethods = new ArrayList<>();
getEntityAnnotatedMethods(screenClazz);
// Accept the real implementation to be proxied
this.screenClazz = screenClazz;
}
/**
* create an page instance
* @param type
* @param
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
public static IPage getInstance(final Class<? extends IPage> type)
throws InstantiationException, IllegalAccessException {
List<Class<?>> interfaces = new ArrayList<>();
interfaces.addAll(Arrays.asList(type.getInterfaces()));
return (IPage) Proxy.newProxyInstance(
type.getClassLoader(),
findInterfaces(type),
new IPageProxy(type)
);
/*return (IPage) Proxy.newProxyInstance(type.getClassLoader(),
interfaces.toArray(new Class<?>[interfaces.size()])
, new IPageProxy(type));*/
}
/**
* get all methods that annotated with @Entity annotation
* and add it for entityMethods array List
* @param screenClazz
*/
private void getEntityAnnotatedMethods(final Class <? extends IPage> screenClazz) {
// Scan each interface method for the specific annotation
// and save each compatible method
for (final Method m : screenClazz.getDeclaredMethods()) {
if (m.isAnnotationPresent(Entity.class)) {
entityMethods.add(m);
}
}
}
static Class<?>[] findInterfaces(final Class<? extends IPage> type) {
Class<?> current = type;
do {
final Class<?>[] interfaces = current.getInterfaces();
if (interfaces.length != 0) {
return interfaces;
}
} while ((current = current.getSuperclass()) != Object.class);
throw new UnsupportedOperationException("The type does not implement any interface");
}
@Override
public Object invoke(
final Object proxy,
final Method method,
final Object[] args) throws InvocationTargetException, IllegalAccessException {
// A method on MyInterface has been called!
// Check if we need to go call it directly or if we need to
// execute something else before!
if (entityMethods.contains(method)) {
// The method exist in our to-be-proxied list
// Execute something and the call it
// ... some other things
System.out.println("Something else");
}
// Invoke original method
return method.invoke(screenClazz, args);
}
}
主要类别:
public class Main {
public static void main(String[] args) {
try {
((EventDesignDialog)getInstance(EventDesignDialog.class)).getEventType();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
public static <T extends IPage> T getInstance(final Class<? extends IPage> type) throws InstantiationException, IllegalAccessException {
return (T) IPageProxy.getInstance(type);
}
}
将引发以下异常:
Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy2 cannot be cast to abc.EventDesignDialog
at abc.Main.main(Main.java:8)
# 1 楼答案
您正在扩展
Screen
,这意味着它不是interface
只有在层次结构中存在基
interface
时,动态代理才能工作因此,代理不能实现任何
interface
,显然它不是Screen
层次结构的一部分如果
Screen
是interface
,那么您的方法仍然太复杂。这个这就足够了
您仍然会收到一个异常,因为
返回由这个类实现的
interface
这意味着如果在
EventDesignDialog.class
上调用它,它将返回一个空数组这意味着如果在
EntityDesignDialog.class
上调用它,它仍然会返回一个空数组在
Screen.class
上调用它时,它将返回你需要在层次结构中循环使用
直到你找到合适的
interface
一个可能的实现可能看起来像
这意味着您需要将代码更改为
但是,由于您已经知道结果将是一个
IPage
代理,您可以这里
你正在返回一个
IPage
,但是在这里你试图把它下放到一个更具体的类型。这是不可能的,因为代理不是
EventDesignDialog
类型,但它只实现了IPage
接口由于动态代理是基于接口的,您将被迫处理接口
尝试强制转换为具体类总是会引发异常
如果你需要一个
IEventDesignDialog
,你需要一个新的代理